home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / samba.idb / usr / samba / src / source / clitar.c.z / clitar.c
Encoding:
C/C++ Source or Header  |  1998-10-28  |  58.6 KB  |  2,382 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Tar Extensions
  5.    Copyright (C) Ricky Poulten 1995-1998
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. /* The following changes developed by Richard Sharpe for Canon Information
  22.    Systems Research Australia (CISRA) are Copyright (C) 1998 by CISRA and are 
  23.    made available under the terms of the GPL as listed above:
  24.  
  25.    1. Restore can now restore files with long file names
  26.    2. Save now saves directory information so that we can restore 
  27.       directory creation times
  28.    3. tar now accepts both UNIX path names and DOS path names. I prefer
  29.       those lovely /'s to those UGLY \'s :-)
  30.    4. the files to exclude can be specified as a regular expression by adding
  31.       an r flag to the other tar flags. Eg:
  32.  
  33.          -TcrX file.tar "*.(obj|exe)"
  34.  
  35.       will skip all .obj and .exe files
  36. */
  37.  
  38.  
  39. #include "includes.h"
  40. #include "clitar.h"
  41.  
  42. typedef struct file_info_struct file_info2;
  43.  
  44. struct file_info_struct
  45. {
  46.   int size;
  47.   int mode;
  48.   int uid;
  49.   int gid;
  50.   /* These times are normally kept in GMT */
  51.   time_t mtime;
  52.   time_t atime;
  53.   time_t ctime;
  54.   char *name;     /* This is dynamically allocate */
  55.  
  56.   file_info2 *next, *prev;  /* Used in the stack ... */
  57.  
  58. };
  59.  
  60. typedef struct
  61. {
  62.   file_info2 *top;
  63.   int items;
  64.  
  65. } stack;
  66.  
  67. stack dir_stack = {NULL, 0}; /* Want an empty stack */
  68.  
  69. extern BOOL recurse;
  70.  
  71. #define SEPARATORS " \t\n\r"
  72. extern int DEBUGLEVEL;
  73. extern int Client;
  74.  
  75. /* These defines are for the do_setrattr routine, to indicate
  76.  * setting and reseting of file attributes in the function call */
  77. #define ATTRSET 1
  78. #define ATTRRESET 0
  79.  
  80. static int attribute = aDIR | aSYSTEM | aHIDDEN;
  81.  
  82. #ifndef CLIENT_TIMEOUT
  83. #define CLIENT_TIMEOUT (30*1000)
  84. #endif
  85.  
  86. static char *tarbuf;
  87. static int tp, ntarf, tbufsiz, ttarf;
  88. /* Incremental mode */
  89. BOOL tar_inc=False;
  90. /* Reset archive bit */
  91. BOOL tar_reset=False;
  92. /* Include / exclude mode (true=include, false=exclude) */
  93. BOOL tar_excl=True;
  94. /* use regular expressions for search on file names */
  95. BOOL tar_re_search=False;
  96. #ifdef HAVE_REGEX_H
  97. regex_t *preg;
  98. #endif
  99. /* Dump files with System attribute */
  100. BOOL tar_system=False;
  101. /* Dump files with Hidden attribute */
  102. BOOL tar_hidden=True;
  103. /* Be noisy - make a catalogue */
  104. BOOL tar_noisy=True;
  105.  
  106. char tar_type='\0';
  107. static char **cliplist=NULL;
  108. static int clipn=0;
  109.  
  110. extern file_info def_finfo;
  111. extern BOOL lowercase;
  112. extern int cnum;
  113. extern BOOL readbraw_supported;
  114. extern int max_xmit;
  115. extern pstring cur_dir;
  116. extern int get_total_time_ms;
  117. extern int get_total_size;
  118. extern int Protocol;
  119.  
  120. int blocksize=20;
  121. int tarhandle;
  122.  
  123. static void writetarheader(int f,  char *aname, int size, time_t mtime,
  124.                char *amode, unsigned char ftype);
  125. static void do_atar(char *rname,char *lname,file_info *finfo1);
  126. static void do_tar(file_info *finfo);
  127. static void oct_it(long value, int ndgs, char *p);
  128. static void fixtarname(char *tptr, char *fp, int l);
  129. static int dotarbuf(int f, char *b, int n);
  130. static void dozerobuf(int f, int n);
  131. static void dotareof(int f);
  132. static void initarbuf(void);
  133. static int do_setrattr(char *fname, int attr, int setit);
  134.  
  135. /* restore functions */
  136. static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix);
  137. static long unoct(char *p, int ndgs);
  138. static void do_tarput(void);
  139. static void unfixtarname(char *tptr, char *fp, int l);
  140.  
  141. /*
  142.  * tar specific utitlities
  143.  */
  144.  
  145. #if 0 /* Removed to get around gcc 'defined but not used' error. */
  146.  
  147. /*
  148.  * Stack routines, push_dir, pop_dir, top_dir_name
  149.  */
  150.  
  151. static BOOL push_dir(stack *tar_dir_stack, file_info2 *dir)
  152. {
  153.   dir -> next = tar_dir_stack -> top;
  154.   dir -> prev = NULL;
  155.   tar_dir_stack -> items++;
  156.   tar_dir_stack -> top = dir;
  157.   return(True);
  158.  
  159. }
  160.  
  161. static file_info2 *pop_dir(stack *tar_dir_stack)
  162. {
  163.   file_info2 *ptr;
  164.   
  165.   ptr = tar_dir_stack -> top;
  166.   if (tar_dir_stack -> top != NULL) {
  167.  
  168.     tar_dir_stack -> top = tar_dir_stack -> top -> next;
  169.     tar_dir_stack -> items--;
  170.  
  171.   }
  172.  
  173.   return ptr;
  174.  
  175. }
  176.  
  177. static char *top_dir_name(stack *tar_dir_stack)
  178. {
  179.  
  180.   return(tar_dir_stack -> top != NULL?tar_dir_stack -> top -> name:NULL);
  181.  
  182. }
  183.  
  184. static BOOL sub_dir(char *dir1, char *dir2)
  185. {
  186.  
  187.   return(True);
  188.  
  189. }
  190.  
  191. #endif /* Removed to get around gcc 'defined but not used' error. */
  192.  
  193. /* Create a string of size size+1 (for the null) */
  194. static char * string_create_s(int size)
  195. {
  196.   char *tmp;
  197.  
  198.   tmp = (char *)malloc(size+1);
  199.  
  200.   if (tmp == NULL) {
  201.  
  202.     DEBUG(0, ("Out of memory in string_create_s\n"));
  203.  
  204.   }
  205.  
  206.   return(tmp);
  207.  
  208. }
  209.  
  210. /****************************************************************************
  211. Write a tar header to buffer
  212. ****************************************************************************/
  213. static void writetarheader(int f,  char *aname, int size, time_t mtime,
  214.                char *amode, unsigned char ftype)
  215. {
  216.   union hblock hb;
  217.   int i, chk, l;
  218.   char *jp;
  219.  
  220.   DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype, size, aname));
  221.  
  222.   memset(hb.dummy, 0, sizeof(hb.dummy));
  223.   
  224.   l=strlen(aname);
  225.   if (l >= NAMSIZ) {
  226.       /* write a GNU tar style long header */
  227.       char *b;
  228.       b = (char *)malloc(l+TBLOCK+100);
  229.       if (!b) {
  230.           DEBUG(0,("out of memory\n"));
  231.           exit(1);
  232.       }
  233.       writetarheader(f, "/./@LongLink", l+1, 0, "     0 \0", 'L');
  234.       memset(b, 0, l+TBLOCK+100);
  235.       fixtarname(b, aname, l+1);
  236.       i = strlen(b)+1;
  237.       DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b)));
  238.       dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1));
  239.       free(b);
  240.   }
  241.  
  242.   /* use l + 1 to do the null too */
  243.   fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
  244.  
  245.   if (lowercase)
  246.     strlower(hb.dbuf.name);
  247.  
  248.   /* write out a "standard" tar format header */
  249.  
  250.   hb.dbuf.name[NAMSIZ-1]='\0';
  251.   fstrcpy(hb.dbuf.mode, amode);
  252.   oct_it(0L, 8, hb.dbuf.uid);
  253.   oct_it(0L, 8, hb.dbuf.gid);
  254.   oct_it((long) size, 13, hb.dbuf.size);
  255.   oct_it((long) mtime, 13, hb.dbuf.mtime);
  256.   memcpy(hb.dbuf.chksum, "        ", sizeof(hb.dbuf.chksum));
  257.   memset(hb.dbuf.linkname, 0, NAMSIZ);
  258.   hb.dbuf.linkflag=ftype;
  259.   
  260.   for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
  261.  
  262.   oct_it((long) chk, 8, hb.dbuf.chksum);
  263.   hb.dbuf.chksum[6] = '\0';
  264.  
  265.   (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
  266. }
  267.  
  268. /****************************************************************************
  269. Read a tar header into a hblock structure, and validate
  270. ***************************************************************************/
  271. static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix)
  272. {
  273.   long chk, fchk;
  274.   int i;
  275.   char *jp;
  276.  
  277.   /*
  278.    * read in a "standard" tar format header - we're not that interested
  279.    * in that many fields, though
  280.    */
  281.  
  282.   /* check the checksum */
  283.   for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++);
  284.  
  285.   if (chk == 0)
  286.     return chk;
  287.  
  288.   /* compensate for blanks in chksum header */
  289.   for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;)
  290.     chk-=(0xFF & *jp++);
  291.  
  292.   chk += ' ' * sizeof(hb->dbuf.chksum);
  293.  
  294.   fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
  295.  
  296.   DEBUG(5, ("checksum totals chk=%d fchk=%d chksum=%s\n",
  297.         chk, fchk, hb->dbuf.chksum));
  298.  
  299.   if (fchk != chk)
  300.     {
  301.       DEBUG(0, ("checksums don't match %d %d\n", fchk, chk));
  302.       return -1;
  303.     }
  304.  
  305.   if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
  306.  
  307.     DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
  308.     return(-1);
  309.  
  310.   }
  311.  
  312.   pstrcpy(finfo->name, prefix);
  313.  
  314.   /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
  315.   unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
  316.            strlen(hb->dbuf.name) + 1);
  317.  
  318. /* can't handle some links at present */
  319.   if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
  320.     if (hb->dbuf.linkflag == 0) {
  321.       DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
  322.         finfo->name));
  323.     } else { 
  324.       if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */
  325.          /* Do nothing here at the moment. do_tarput will handle this
  326.             as long as the longlink gets back to it, as it has to advance 
  327.             the buffer pointer, etc */
  328.  
  329.       } else {
  330.         DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n"));
  331.         return -2;
  332.       }
  333.     }
  334.   }
  335.     
  336.   if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR)
  337.     || (*(finfo->name+strlen(finfo->name)-1) == '\\'))
  338.     {
  339.       finfo->mode=aDIR;
  340.     }
  341.   else
  342.     finfo->mode=0; /* we don't care about mode at the moment, we'll
  343.             * just make it a regular file */
  344.   /*
  345.    * Bug fix by richard@sj.co.uk
  346.    *
  347.    * REC: restore times correctly (as does tar)
  348.    * We only get the modification time of the file; set the creation time
  349.    * from the mod. time, and the access time to current time
  350.    */
  351.   finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8);
  352.   finfo->atime = time(NULL);
  353.   finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size));
  354.  
  355.   return True;
  356. }
  357.  
  358. /****************************************************************************
  359. Write out the tar buffer to tape or wherever
  360. ****************************************************************************/
  361. static int dotarbuf(int f, char *b, int n)
  362. {
  363.   int fail=1, writ=n;
  364.  
  365.   /* This routine and the next one should be the only ones that do write()s */
  366.   if (tp + n >= tbufsiz)
  367.     {
  368.       int diff;
  369.  
  370.       diff=tbufsiz-tp;
  371.       memcpy(tarbuf + tp, b, diff);
  372.       fail=fail && (1+write(f, tarbuf, tbufsiz));
  373.       n-=diff;
  374.       b+=diff;
  375.       tp=0;
  376.  
  377.       while (n >= tbufsiz)
  378.     {
  379.       fail=fail && (1 + write(f, b, tbufsiz));
  380.       n-=tbufsiz;
  381.       b+=tbufsiz;
  382.     }
  383.     }
  384.   if (n>0) {
  385.     memcpy(tarbuf+tp, b, n);
  386.     tp+=n;
  387.   }
  388.  
  389.   return(fail ? writ : 0);
  390. }
  391.  
  392. /****************************************************************************
  393. Write zeros to buffer / tape
  394. ****************************************************************************/
  395. static void dozerobuf(int f, int n)
  396. {
  397.   /* short routine just to write out n zeros to buffer -
  398.    * used to round files to nearest block
  399.    * and to do tar EOFs */
  400.  
  401.   if (n+tp >= tbufsiz)
  402.     {
  403.       memset(tarbuf+tp, 0, tbufsiz-tp);
  404.  
  405.       write(f, tarbuf, tbufsiz);
  406.       memset(tarbuf, 0, (tp+=n-tbufsiz));
  407.     }
  408.   else
  409.     {
  410.       memset(tarbuf+tp, 0, n);
  411.       tp+=n;
  412.     }
  413. }
  414.  
  415. /****************************************************************************
  416. Malloc tape buffer
  417. ****************************************************************************/
  418. static void initarbuf()
  419. {
  420.   /* initialize tar buffer */
  421.   tbufsiz=blocksize*TBLOCK;
  422.   tarbuf=malloc(tbufsiz);      /* FIXME: We might not get the buffer */
  423.  
  424.   /* reset tar buffer pointer and tar file counter and total dumped */
  425.   tp=0; ntarf=0; ttarf=0;
  426. }
  427.  
  428. /****************************************************************************
  429. Write two zero blocks at end of file
  430. ****************************************************************************/
  431. static void dotareof(int f)
  432. {
  433.   struct stat stbuf;
  434.   /* Two zero blocks at end of file, write out full buffer */
  435.  
  436.   (void) dozerobuf(f, TBLOCK);
  437.   (void) dozerobuf(f, TBLOCK);
  438.  
  439.   if (fstat(f, &stbuf) == -1)
  440.     {
  441.       DEBUG(0, ("Couldn't stat file handle\n"));
  442.       return;
  443.     }
  444.  
  445.   /* Could be a pipe, in which case S_ISREG should fail,
  446.    * and we should write out at full size */
  447.   if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
  448. }
  449.  
  450. /****************************************************************************
  451. (Un)mangle DOS pathname, make nonabsolute
  452. ****************************************************************************/
  453. static void fixtarname(char *tptr, char *fp, int l)
  454. {
  455.   /* add a '.' to start of file name, convert from ugly dos \'s in path
  456.    * to lovely unix /'s :-} */
  457.  
  458.   *tptr++='.';
  459.  
  460.   while (l > 0) {
  461.     int skip;
  462.     if((skip = skip_multibyte_char( *fp)) != 0) {
  463.       if (skip == 2) {
  464.         *tptr++ = *fp++;
  465.         *tptr++ = *fp++;
  466.         l -= 2;
  467.       } else if (skip == 1) {
  468.         *tptr++ = *fp++;
  469.         l--;
  470.       }
  471.     } else if (*fp == '\\') {
  472.       *tptr++ = '/';
  473.       fp++;
  474.       l--;
  475.     } else {
  476.       *tptr++ = *fp++;
  477.       l--;
  478.     }
  479.   }
  480. }
  481.  
  482. /****************************************************************************
  483. Convert from decimal to octal string
  484. ****************************************************************************/
  485. static void oct_it (long value, int ndgs, char *p)
  486. {
  487.   /* Converts long to octal string, pads with leading zeros */
  488.  
  489.   /* skip final null, but do final space */
  490.   --ndgs;
  491.   p[--ndgs] = ' ';
  492.  
  493.   /* Loop does at least one digit */
  494.   do {
  495.       p[--ndgs] = '0' + (char) (value & 7);
  496.       value >>= 3;
  497.     }
  498.   while (ndgs > 0 && value != 0);
  499.  
  500.   /* Do leading zeros */
  501.   while (ndgs > 0)
  502.     p[--ndgs] = '0';
  503. }
  504.  
  505. /****************************************************************************
  506. Convert from octal string to long
  507. ***************************************************************************/
  508. static long unoct(char *p, int ndgs)
  509. {
  510.   long value=0;
  511.   /* Converts octal string to long, ignoring any non-digit */
  512.  
  513.   while (--ndgs)
  514.     {
  515.       if (isdigit(*p))
  516.         value = (value << 3) | (long) (*p - '0');
  517.  
  518.       p++;
  519.     }
  520.  
  521.   return value;
  522. }
  523.  
  524. /****************************************************************************
  525. Compare two strings in a slash insensitive way, allowing s1 to match s2 
  526. if s1 is an "initial" string (up to directory marker).  Thus, if s2 is 
  527. a file in any subdirectory of s1, declare a match.
  528. ***************************************************************************/
  529. static int strslashcmp(char *s1, char *s2)
  530. {
  531.   char *s1_0=s1;
  532.  
  533.   while(*s1 && *s2 &&
  534.     (*s1 == *s2
  535.      || tolower(*s1) == tolower(*s2)
  536.      || (*s1 == '\\' && *s2=='/')
  537.      || (*s1 == '/' && *s2=='\\'))) {
  538.       s1++; s2++;
  539.   }
  540.  
  541.   /* if s1 has a trailing slash, it compared equal, so s1 is an "initial" 
  542.      string of s2.
  543.    */
  544.   if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0;
  545.  
  546.   /* ignore trailing slash on s1 */
  547.   if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0;
  548.  
  549.   /* check for s1 is an "initial" string of s2 */
  550.   if (*s2 == '/' || *s2 == '\\') return 0;
  551.  
  552.   return *s1-*s2;
  553. }
  554.  
  555. /*
  556.  * general smb utility functions
  557.  */
  558. /**********************************************************************
  559. do_setrtime, set time on a file or dir ...
  560. **********************************************************************/
  561.  
  562. static int do_setrtime(char *fname, int mtime)
  563. {
  564.   char *inbuf, *outbuf, *p;
  565.   char *name;
  566.  
  567.   DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname, strlen(fname)));
  568.  
  569.   name = (char *)malloc(strlen(fname) + 1 + 1);
  570.   if (name == NULL) {
  571.  
  572.      DEBUG(0, ("Failed to allocate space while setting time on file: %s", fname));
  573.      return False;
  574.  
  575.   }
  576.  
  577.   pstrcpy(name, fname);
  578.   pstrcpy(fname, "\\");
  579.   pstrcat(fname, name);
  580.  
  581.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  582.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  583.  
  584.   if (!inbuf || !outbuf) {
  585.  
  586.     DEBUG(0, ("Could not allocate memory for inbuf or outbuf while changing time on: %s\n", fname));
  587.     return False;
  588.  
  589.   }
  590.  
  591.   memset(outbuf, 0, smb_size);
  592.   set_message(outbuf, 8, 4 + strlen(fname), True);
  593.   CVAL(outbuf, smb_com) = SMBsetatr;
  594.   SSVAL(outbuf, smb_tid, cnum);
  595.   cli_setup_pkt(outbuf);
  596.  
  597.   SSVAL(outbuf, smb_vwv0, 0);
  598.   put_dos_date3(outbuf, smb_vwv1, mtime);
  599.  
  600.   p = smb_buf(outbuf);
  601.   *p++ = 4;
  602.   pstrcpy(p, fname);
  603.   p+= (strlen(fname)+1);
  604.  
  605.   *p++ = 4;
  606.   *p++ = 0;
  607.  
  608.   send_smb(Client, outbuf);
  609.   client_receive_smb(Client, inbuf, CLIENT_TIMEOUT);
  610.  
  611.   if (CVAL(inbuf,smb_rcls) != 0)
  612.     {
  613.       DEBUG(0,("%s setting attributes on file %s\n",
  614.         smb_errstr(inbuf), fname));
  615.       free(inbuf);free(outbuf);
  616.       return(False);
  617.     }
  618.  
  619.   free(inbuf);free(outbuf);
  620.   return(True);
  621.  
  622. }
  623.  
  624. /****************************************************************************
  625. Set DOS file attributes
  626. ***************************************************************************/
  627. static int do_setrattr(char *fname, int attr, int setit)
  628. {
  629.   /*
  630.    * First get the existing attribs from existing file
  631.    */
  632.   char *inbuf,*outbuf;
  633.   char *p;
  634.   pstring name;
  635.   int fattr;
  636.  
  637.   pstrcpy(name,fname);
  638.   pstrcpy(fname,"\\");
  639.   pstrcat(fname,name);
  640.  
  641.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  642.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  643.  
  644.   if (!inbuf || !outbuf)
  645.     {
  646.       DEBUG(0,("out of memory\n"));
  647.       return False;
  648.     }
  649.  
  650.   /* send an smb getatr message */
  651.  
  652.   memset(outbuf,0,smb_size);
  653.   set_message(outbuf,0,2 + strlen(fname),True);
  654.   CVAL(outbuf,smb_com) = SMBgetatr;
  655.   SSVAL(outbuf,smb_tid,cnum);
  656.   cli_setup_pkt(outbuf);
  657.  
  658.   p = smb_buf(outbuf);
  659.   *p++ = 4;
  660.   pstrcpy(p,fname);
  661.   p += (strlen(fname)+1);
  662.   
  663.   *p++ = 4;
  664.   *p++ = 0;
  665.  
  666.   send_smb(Client,outbuf);
  667.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  668.  
  669.   if (CVAL(inbuf,smb_rcls) != 0)
  670.     DEBUG(5,("getatr: %s\n",smb_errstr(inbuf)));
  671.   else
  672.     {
  673.       DEBUG(5,("\nattr 0x%X  time %d  size %d\n",
  674.            (int)CVAL(inbuf,smb_vwv0),
  675.            SVAL(inbuf,smb_vwv1),
  676.            SVAL(inbuf,smb_vwv3)));
  677.     }
  678.  
  679.   fattr=CVAL(inbuf,smb_vwv0);
  680.  
  681.   /* combine found attributes with bits to be set or reset */
  682.  
  683.   attr=setit ? (fattr | attr) : (fattr & ~attr);
  684.  
  685.   /* now try and set attributes by sending smb reset message */
  686.  
  687.   /* clear out buffer and start again */
  688.   memset(outbuf,0,smb_size);
  689.   set_message(outbuf,8,4 + strlen(fname),True);
  690.   CVAL(outbuf,smb_com) = SMBsetatr;
  691.   SSVAL(outbuf,smb_tid,cnum);
  692.   cli_setup_pkt(outbuf);
  693.  
  694.   SSVAL(outbuf,smb_vwv0,attr);
  695.   
  696.   p = smb_buf(outbuf);
  697.   *p++ = 4;      
  698.   pstrcpy(p,fname);
  699.   p += (strlen(fname)+1);
  700.   
  701.   *p++ = 4;
  702.   *p++ = 0;
  703.  
  704.   send_smb(Client,outbuf);
  705.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  706.   
  707.   if (CVAL(inbuf,smb_rcls) != 0)
  708.     {
  709.       DEBUG(0,("%s setting attributes on file %s\n",
  710.         smb_errstr(inbuf), fname));
  711.       free(inbuf);free(outbuf);
  712.       return(False);
  713.     }
  714.  
  715.   free(inbuf);free(outbuf);
  716.   return(True);
  717. }
  718.  
  719. /****************************************************************************
  720. Create a file on a share
  721. ***************************************************************************/
  722. static BOOL smbcreat(file_info2 finfo, int *fnum, char *inbuf, char *outbuf)
  723. {
  724.   char *p;
  725.   /* *must* be called with buffer ready malloc'ed */
  726.   /* open remote file */
  727.  
  728.   memset(outbuf,0,smb_size);
  729.   set_message(outbuf,3,2 + strlen(finfo.name),True);
  730.   CVAL(outbuf,smb_com) = SMBcreate;
  731.   SSVAL(outbuf,smb_tid,cnum);
  732.   cli_setup_pkt(outbuf);
  733.   
  734.   SSVAL(outbuf,smb_vwv0,finfo.mode);
  735.   put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
  736.   
  737.   p = smb_buf(outbuf);
  738.   *p++ = 4;      
  739.   pstrcpy(p,finfo.name);
  740.   
  741.   send_smb(Client,outbuf);
  742.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  743.   
  744.   if (CVAL(inbuf,smb_rcls) != 0)
  745.     {
  746.       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),
  747.            finfo.name));
  748.       return 0;
  749.     }
  750.   
  751.   *fnum = SVAL(inbuf,smb_vwv0);
  752.   return True;
  753. }
  754.  
  755. /****************************************************************************
  756. Write a file to a share
  757. ***************************************************************************/
  758. static BOOL smbwrite(int fnum, int n, int low, int high, int left,
  759.              char *bufferp, char *inbuf, char *outbuf)
  760. {
  761.   /* *must* be called with buffer ready malloc'ed */
  762.  
  763.   memset(outbuf,0,smb_size);
  764.   set_message(outbuf,5,n + 3,True);
  765.   
  766.   memcpy(smb_buf(outbuf)+3, bufferp, n);
  767.   
  768.   set_message(outbuf,5,n + 3, False);
  769.   CVAL(outbuf,smb_com) = SMBwrite;
  770.   SSVAL(outbuf,smb_tid,cnum);
  771.   cli_setup_pkt(outbuf);
  772.   
  773.   SSVAL(outbuf,smb_vwv0,fnum);
  774.   SSVAL(outbuf,smb_vwv1,n);
  775.   SIVAL(outbuf,smb_vwv2,low);
  776.   SSVAL(outbuf,smb_vwv4,left);
  777.   CVAL(smb_buf(outbuf),0) = 1;
  778.   SSVAL(smb_buf(outbuf),1,n);
  779.  
  780.   send_smb(Client,outbuf); 
  781.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  782.   
  783.   if (CVAL(inbuf,smb_rcls) != 0)
  784.     {
  785.       DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
  786.       return False;
  787.     }
  788.   
  789.   if (n != SVAL(inbuf,smb_vwv0))
  790.     {
  791.       DEBUG(0,("Error: only wrote %d bytes out of %d\n",
  792.            SVAL(inbuf,smb_vwv0), n));
  793.       return False;
  794.     }
  795.  
  796.   return True;
  797. }
  798.  
  799. /****************************************************************************
  800. Close a file on a share
  801. ***************************************************************************/
  802. static BOOL smbshut(file_info2 finfo, int fnum, char *inbuf, char *outbuf)
  803. {
  804.   /* *must* be called with buffer ready malloc'ed */
  805.  
  806.   memset(outbuf,0,smb_size);
  807.   set_message(outbuf,3,0,True);
  808.   CVAL(outbuf,smb_com) = SMBclose;
  809.   SSVAL(outbuf,smb_tid,cnum);
  810.   cli_setup_pkt(outbuf);
  811.   
  812.   SSVAL(outbuf,smb_vwv0,fnum);
  813.   put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
  814.   
  815.   DEBUG(3,("Setting date to %s (0x%X)",
  816.        asctime(LocalTime(&finfo.mtime)),
  817.        finfo.mtime));
  818.   
  819.   send_smb(Client,outbuf);
  820.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  821.   
  822.   if (CVAL(inbuf,smb_rcls) != 0)
  823.     {
  824.       DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),
  825.            finfo.name));
  826.       return False;
  827.     }
  828.  
  829.   return True;
  830. }
  831.  
  832. /****************************************************************************
  833. Verify existence of path on share
  834. ***************************************************************************/
  835. static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
  836. {
  837.   char *p;
  838.  
  839.   memset(outbuf,0,smb_size);
  840.   set_message(outbuf,0,4 + strlen(fname),True);
  841.   CVAL(outbuf,smb_com) = SMBchkpth;
  842.   SSVAL(outbuf,smb_tid,cnum);
  843.   cli_setup_pkt(outbuf);
  844.  
  845.   p = smb_buf(outbuf);
  846.   *p++ = 4;
  847.   pstrcpy(p,fname);
  848.  
  849.   send_smb(Client,outbuf);
  850.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  851.  
  852.   DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf)));
  853.  
  854.   return(CVAL(inbuf,smb_rcls) == 0);
  855. }
  856.  
  857. /****************************************************************************
  858. Make a directory on share
  859. ***************************************************************************/
  860. static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
  861. {
  862.   /* *must* be called with buffer ready malloc'ed */
  863.   char *p;
  864.  
  865.   memset(outbuf,0,smb_size);
  866.   set_message(outbuf,0,2 + strlen(fname),True);
  867.   
  868.   CVAL(outbuf,smb_com) = SMBmkdir;
  869.   SSVAL(outbuf,smb_tid,cnum);
  870.   cli_setup_pkt(outbuf);
  871.   
  872.   p = smb_buf(outbuf);
  873.   *p++ = 4;      
  874.   pstrcpy(p,fname);
  875.   
  876.   send_smb(Client,outbuf);
  877.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  878.   
  879.   if (CVAL(inbuf,smb_rcls) != 0)
  880.     {
  881.       DEBUG(0,("%s making remote directory %s\n",
  882.            smb_errstr(inbuf),fname));
  883.       return(False);
  884.     }
  885.  
  886.   return(True);
  887. }
  888.  
  889. /****************************************************************************
  890. Ensure a remote path exists (make if necessary)
  891. ***************************************************************************/
  892. static BOOL ensurepath(char *fname, char *inbuf, char *outbuf)
  893. {
  894.   /* *must* be called with buffer ready malloc'ed */
  895.   /* ensures path exists */
  896.  
  897.   char *partpath, *ffname;
  898.   char *p=fname, *basehack;
  899.  
  900.   DEBUG(5, ( "Ensurepath called with: %s\n", fname));
  901.  
  902.   partpath = string_create_s(strlen(fname));
  903.   ffname = string_create_s(strlen(fname));
  904.  
  905.   if ((partpath == NULL) || (ffname == NULL)){
  906.  
  907.     DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
  908.     return(False);
  909.  
  910.   }
  911.  
  912.   *partpath = 0;
  913.  
  914.   /* fname copied to ffname so can strtok */
  915.  
  916.   pstrcpy(ffname, fname);
  917.  
  918.   /* do a `basename' on ffname, so don't try and make file name directory */
  919.   if ((basehack=strrchr(ffname, '\\')) == NULL)
  920.     return True;
  921.   else
  922.     *basehack='\0';
  923.  
  924.   p=strtok(ffname, "\\");
  925.  
  926.   while (p)
  927.     {
  928.       pstrcat(partpath, p);
  929.  
  930.       if (!smbchkpath(partpath, inbuf, outbuf)) {
  931.     if (!smbmkdir(partpath, inbuf, outbuf))
  932.       {
  933.         DEBUG(0, ("Error mkdirhiering\n"));
  934.         return False;
  935.       }
  936.     else
  937.       DEBUG(3, ("mkdirhiering %s\n", partpath));
  938.  
  939.       }
  940.  
  941.       pstrcat(partpath, "\\");
  942.       p = strtok(NULL,"/\\");
  943.     }
  944.  
  945.     return True;
  946. }
  947.  
  948. int padit(char *buf, int bufsize, int padsize)
  949. {
  950.   int berr= 0;
  951.   int bytestowrite;
  952.   
  953.   DEBUG(5, ("Padding with %d zeros\n", padsize));
  954.   memset(buf, 0, bufsize);
  955.   while( !berr && padsize > 0 ) {
  956.     bytestowrite= MIN(bufsize, padsize);
  957.     berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite;
  958.     padsize -= bytestowrite;
  959.   }
  960.   
  961.   return berr;
  962. }
  963.  
  964. /*
  965.  * smbclient functions
  966.  */
  967. /****************************************************************************
  968. append one remote file to the tar file
  969. ***************************************************************************/
  970. static void do_atar(char *rname,char *lname,file_info *finfo1)
  971. {
  972.   int fnum;
  973.   uint32 nread=0;
  974.   char *p, ftype;
  975.   char *inbuf,*outbuf;
  976.   file_info finfo;
  977.   BOOL close_done = False;
  978.   BOOL shallitime=True;
  979.   BOOL ignore_close_error = False;
  980.   char *dataptr=NULL;
  981.   int datalen=0;
  982.  
  983.   struct timeval tp_start;
  984.   GetTimeOfDay(&tp_start);
  985.  
  986.   ftype = '0'; /* An ordinary file ... */
  987.  
  988.   if (finfo1) 
  989.     finfo = *finfo1;
  990.   else
  991.     finfo = def_finfo;
  992.  
  993.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  994.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  995.  
  996.   if (!inbuf || !outbuf)
  997.     {
  998.       DEBUG(0,("out of memory\n"));
  999.       return;
  1000.     }
  1001.  
  1002.   memset(outbuf,0,smb_size);
  1003.   set_message(outbuf,15,1 + strlen(rname),True);
  1004.  
  1005.   CVAL(outbuf,smb_com) = SMBopenX;
  1006.   SSVAL(outbuf,smb_tid,cnum);
  1007.   cli_setup_pkt(outbuf);
  1008.  
  1009.   SSVAL(outbuf,smb_vwv0,0xFF);
  1010.   SSVAL(outbuf,smb_vwv2,1);
  1011.   SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
  1012.   SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
  1013.   SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
  1014.   SSVAL(outbuf,smb_vwv8,1);
  1015.  
  1016.   p = smb_buf(outbuf);
  1017.   pstrcpy(p,rname);
  1018.   p = skip_string(p,1);
  1019.  
  1020.   dos_clean_name(rname);
  1021.  
  1022.   /* do a chained openX with a readX? */  
  1023.   if (finfo.size > 0)
  1024.     {
  1025.       SSVAL(outbuf,smb_vwv0,SMBreadX);
  1026.       SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
  1027.       memset(p,0,200);
  1028.       p -= smb_wct;
  1029.       SSVAL(p,smb_wct,10);
  1030.       SSVAL(p,smb_vwv0,0xFF);
  1031.       SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
  1032.       SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
  1033.       smb_setlen(outbuf,smb_len(outbuf)+11*2+1);  
  1034.     }
  1035.   
  1036.   send_smb(Client,outbuf);
  1037.   client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1038.  
  1039.   if (CVAL(inbuf,smb_rcls) != 0)
  1040.     {
  1041.       if (CVAL(inbuf,smb_rcls) == ERRSRV &&
  1042.       SVAL(inbuf,smb_err) == ERRnoresource &&
  1043.       cli_reopen_connection(inbuf,outbuf))
  1044.     {
  1045.       do_atar(rname,lname,finfo1);
  1046.       free(inbuf);free(outbuf);
  1047.       return;
  1048.     }
  1049.  
  1050.       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname));
  1051.       free(inbuf);free(outbuf);
  1052.       return;
  1053.     }
  1054.  
  1055.   pstrcpy(finfo.name,rname);
  1056.   if (!finfo1)
  1057.     {
  1058.       finfo.mode = SVAL(inbuf,smb_vwv3);
  1059.       finfo.size = IVAL(inbuf,smb_vwv4);
  1060.       finfo.mtime = make_unix_date3(inbuf+smb_vwv6);
  1061.       finfo.atime = finfo.ctime = finfo.mtime;
  1062.     }
  1063.  
  1064.   DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
  1065.  
  1066.   fnum = SVAL(inbuf,smb_vwv2);
  1067.  
  1068.   if (tar_inc && !(finfo.mode & aARCH))
  1069.     {
  1070.       DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
  1071.       shallitime=0;
  1072.     }
  1073.   else if (!tar_system && (finfo.mode & aSYSTEM))
  1074.     {
  1075.       DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
  1076.       shallitime=0;
  1077.     }
  1078.   else if (!tar_hidden && (finfo.mode & aHIDDEN))
  1079.     {
  1080.       DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
  1081.       shallitime=0;
  1082.     }
  1083.   else
  1084.     {
  1085.       if (SVAL(inbuf,smb_vwv0) == SMBreadX)
  1086.     {
  1087.       p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct;
  1088.       datalen = SVAL(p,smb_vwv5);
  1089.       dataptr = inbuf + 4 + SVAL(p,smb_vwv6);
  1090.     }
  1091.       else
  1092.     {
  1093.       dataptr = NULL;
  1094.       datalen = 0;
  1095.     }
  1096.  
  1097.       DEBUG(3,("getting file %s of size %d bytes as a tar file %s",
  1098.            finfo.name,
  1099.            finfo.size,
  1100.            lname));
  1101.       
  1102.       /* write a tar header, don't bother with mode - just set to 100644 */
  1103.       writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype);
  1104.       
  1105.       while (nread < finfo.size && !close_done)
  1106.     {
  1107.       int method = -1;
  1108.       static BOOL can_chain_close=True;
  1109.  
  1110.       p=NULL;
  1111.       
  1112.       DEBUG(3,("nread=%d\n",nread));
  1113.       
  1114.       /* 3 possible read types. readbraw if a large block is required.
  1115.          readX + close if not much left and read if neither is supported */
  1116.  
  1117.       /* we might have already read some data from a chained readX */
  1118.       if (dataptr && datalen>0)
  1119.         method=3;
  1120.       
  1121.       /* if we can finish now then readX+close */
  1122.       if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) && 
  1123.           ((finfo.size - nread) < 
  1124.            (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
  1125.         method = 0;
  1126.       
  1127.       /* if we support readraw then use that */
  1128.       if (method<0 && readbraw_supported)
  1129.         method = 1;
  1130.       
  1131.       /* if we can then use readX */
  1132.       if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
  1133.         method = 2;
  1134.       
  1135.       
  1136.       switch (method)
  1137.         {
  1138.           /* use readX */
  1139.         case 0:
  1140.         case 2:
  1141.           if (method == 0)
  1142.         close_done = True;
  1143.           
  1144.           /* use readX + close */
  1145.           memset(outbuf,0,smb_size);
  1146.           set_message(outbuf,10,0,True);
  1147.           CVAL(outbuf,smb_com) = SMBreadX;
  1148.           SSVAL(outbuf,smb_tid,cnum);
  1149.           cli_setup_pkt(outbuf);
  1150.           
  1151.           if (close_done)
  1152.         {
  1153.           CVAL(outbuf,smb_vwv0) = SMBclose;
  1154.           SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4);
  1155.         }
  1156.           else
  1157.         CVAL(outbuf,smb_vwv0) = 0xFF;          
  1158.           
  1159.           
  1160.           SSVAL(outbuf,smb_vwv2,fnum);
  1161.           SIVAL(outbuf,smb_vwv3,nread);
  1162.           SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
  1163.           SSVAL(outbuf,smb_vwv6,0);
  1164.           SIVAL(outbuf,smb_vwv7,0);
  1165.           SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread));
  1166.           
  1167.           if (close_done)
  1168.         {
  1169.           p = smb_buf(outbuf);
  1170.           memset(p,0,9);
  1171.           
  1172.           CVAL(p,0) = 3;
  1173.           SSVAL(p,1,fnum);
  1174.           SIVALS(p,3,-1);
  1175.           
  1176.           /* now set the total packet length */
  1177.           smb_setlen(outbuf,smb_len(outbuf)+9);
  1178.         }
  1179.           
  1180.           send_smb(Client,outbuf);
  1181.           client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1182.           
  1183.           if (CVAL(inbuf,smb_rcls) != 0)
  1184.         {
  1185.           DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
  1186.           break;
  1187.         }
  1188.           
  1189.           if (close_done &&
  1190.           SVAL(inbuf,smb_vwv0) != SMBclose)
  1191.         {
  1192.           /* NOTE: WfWg sometimes just ignores the chained
  1193.              command! This seems to break the spec? */
  1194.           DEBUG(3,("Rejected chained close?\n"));
  1195.           close_done = False;
  1196.           can_chain_close = False;
  1197.           ignore_close_error = True;
  1198.         }
  1199.           
  1200.           datalen = SVAL(inbuf,smb_vwv5);
  1201.           dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6);
  1202.           break;
  1203.           
  1204.           
  1205.           /* use readbraw */
  1206.         case 1:
  1207.           {
  1208.         static int readbraw_size = 0xFFFF;
  1209.         
  1210.         extern int Client;
  1211.         memset(outbuf,0,smb_size);
  1212.         set_message(outbuf,8,0,True);
  1213.         CVAL(outbuf,smb_com) = SMBreadbraw;
  1214.         SSVAL(outbuf,smb_tid,cnum);
  1215.         cli_setup_pkt(outbuf);
  1216.         SSVAL(outbuf,smb_vwv0,fnum);
  1217.         SIVAL(outbuf,smb_vwv1,nread);
  1218.         SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
  1219.         SSVAL(outbuf,smb_vwv4,0);
  1220.         SIVALS(outbuf,smb_vwv5,-1);
  1221.         send_smb(Client,outbuf);
  1222.         
  1223.         /* Now read the raw data into the buffer and write it */      
  1224.         if(read_smb_length(Client,inbuf,0) == -1) {
  1225.           DEBUG(0,("Failed to read length in readbraw\n"));        
  1226.           exit(1);
  1227.         }
  1228.         
  1229.         /* Even though this is not an smb message, smb_len
  1230.            returns the generic length of an smb message */
  1231.         datalen = smb_len(inbuf);
  1232.         
  1233.         if (datalen == 0)
  1234.           {
  1235.             /* we got a readbraw error */
  1236.             DEBUG(4,("readbraw error - reducing size\n"));
  1237.             readbraw_size = (readbraw_size * 9) / 10;
  1238.             
  1239.             if (readbraw_size < max_xmit)
  1240.               {
  1241.             DEBUG(0,("disabling readbraw\n"));
  1242.             readbraw_supported = False;
  1243.               }
  1244.  
  1245.             dataptr=NULL;
  1246.             continue;
  1247.           }
  1248.  
  1249.         if(read_data(Client,inbuf,datalen) != datalen) {
  1250.           DEBUG(0,("Failed to read data in readbraw\n"));
  1251.           exit(1);
  1252.         }
  1253.         dataptr = inbuf;
  1254.           }
  1255.           break;
  1256.  
  1257.         case 3:
  1258.           /* we've already read some data with a chained readX */
  1259.           break;
  1260.           
  1261.         default:
  1262.           /* use plain read */
  1263.           memset(outbuf,0,smb_size);
  1264.           set_message(outbuf,5,0,True);
  1265.           CVAL(outbuf,smb_com) = SMBread;
  1266.           SSVAL(outbuf,smb_tid,cnum);
  1267.           cli_setup_pkt(outbuf);
  1268.           
  1269.           SSVAL(outbuf,smb_vwv0,fnum);
  1270.           SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
  1271.           SIVAL(outbuf,smb_vwv2,nread);
  1272.           SSVAL(outbuf,smb_vwv4,finfo.size - nread);
  1273.           
  1274.           send_smb(Client,outbuf);
  1275.           client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1276.           
  1277.           if (CVAL(inbuf,smb_rcls) != 0)
  1278.         {
  1279.           DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
  1280.           break;
  1281.         }
  1282.           
  1283.           datalen = SVAL(inbuf,smb_vwv0);
  1284.           dataptr = smb_buf(inbuf) + 3;
  1285.           break;
  1286.         }
  1287.       
  1288.       
  1289.       /* add received bits of file to buffer - dotarbuf will
  1290.        * write out in 512 byte intervals */
  1291.       if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
  1292.         {
  1293.           DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
  1294.           break;
  1295.         }
  1296.       
  1297.       nread += datalen;
  1298.       if (datalen == 0) 
  1299.         {
  1300.           DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
  1301.           break;
  1302.         }
  1303.  
  1304.       dataptr=NULL;
  1305.       datalen=0;
  1306.     }
  1307.  
  1308.        /* pad tar file with zero's if we couldn't get entire file */
  1309.        if (nread < finfo.size)
  1310.         {
  1311.           DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
  1312.           if (padit(inbuf, BUFFER_SIZE, finfo.size - nread))
  1313.               DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
  1314.         }
  1315.  
  1316.       /* round tar file to nearest block */
  1317.       if (finfo.size % TBLOCK)
  1318.     dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK));
  1319.       
  1320.       ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
  1321.       ntarf++;
  1322.     }
  1323.   
  1324.   if (!close_done)
  1325.     {
  1326.       memset(outbuf,0,smb_size);
  1327.       set_message(outbuf,3,0,True);
  1328.       CVAL(outbuf,smb_com) = SMBclose;
  1329.       SSVAL(outbuf,smb_tid,cnum);
  1330.       cli_setup_pkt(outbuf);
  1331.       
  1332.       SSVAL(outbuf,smb_vwv0,fnum);
  1333.       SIVALS(outbuf,smb_vwv1,-1);
  1334.       
  1335.       send_smb(Client,outbuf);
  1336.       client_receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1337.       
  1338.       if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
  1339.     {
  1340.       DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
  1341.       free(inbuf);free(outbuf);
  1342.       return;
  1343.     }
  1344.     }
  1345.  
  1346.   if (shallitime)
  1347.     {
  1348.       struct timeval tp_end;
  1349.       int this_time;
  1350.  
  1351.       /* if shallitime is true then we didn't skip */
  1352.       if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
  1353.       
  1354.       GetTimeOfDay(&tp_end);
  1355.       this_time = 
  1356.     (tp_end.tv_sec - tp_start.tv_sec)*1000 +
  1357.       (tp_end.tv_usec - tp_start.tv_usec)/1000;
  1358.       get_total_time_ms += this_time;
  1359.       get_total_size += finfo.size;
  1360.  
  1361.       /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */
  1362.       DEBUG(3,("(%g kb/s) (average %g kb/s)\n",
  1363.            finfo.size / MAX(0.001, (1.024*this_time)),
  1364.            get_total_size / MAX(0.001, (1.024*get_total_time_ms))));
  1365.       if (tar_noisy)
  1366.     {
  1367.       printf("%10d (%7.1f kb/s) %s\n",
  1368.            finfo.size, finfo.size / MAX(0.001, (1.024*this_time)),
  1369.                finfo.name);
  1370.     }
  1371.  
  1372.     }
  1373.   
  1374.   free(inbuf);free(outbuf);
  1375. }
  1376.  
  1377. /****************************************************************************
  1378. Append single file to tar file (or not)
  1379. ***************************************************************************/
  1380. static void do_tar(file_info *finfo)
  1381. {
  1382.   pstring rname;
  1383.  
  1384.   if (strequal(finfo->name,".."))
  1385.     return;
  1386.  
  1387.   /* Is it on the exclude list ? */
  1388.   if (!tar_excl && clipn) {
  1389.     pstring exclaim;
  1390.  
  1391.     pstrcpy(exclaim, cur_dir);
  1392.     *(exclaim+strlen(exclaim)-1)='\0';
  1393.  
  1394.     pstrcat(exclaim, "\\");
  1395.     pstrcat(exclaim, finfo->name);
  1396.  
  1397.     DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
  1398.  
  1399.     if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
  1400. #ifdef HAVE_REGEX_H
  1401.     (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
  1402. #else
  1403.         (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) {
  1404. #endif
  1405.       DEBUG(3,("Skipping file %s\n", exclaim));
  1406.       return;
  1407.     }
  1408.   }
  1409.  
  1410.   if (finfo->mode & aDIR)
  1411.     {
  1412.       pstring saved_curdir;
  1413.       pstring mtar_mask;
  1414.       char *inbuf,*outbuf;
  1415.  
  1416.       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1417.       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1418.  
  1419.       if (!inbuf || !outbuf)
  1420.     {
  1421.       DEBUG(0,("out of memory\n"));
  1422.       return;
  1423.     }
  1424.  
  1425.       pstrcpy(saved_curdir,cur_dir);
  1426.  
  1427.       pstrcat(cur_dir,finfo->name);
  1428.       pstrcat(cur_dir,"\\");
  1429.  
  1430.       DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
  1431.  
  1432.       /* write a tar directory, don't bother with mode - just set it to
  1433.        * 40755 */
  1434.       writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5');
  1435.       ntarf++;  /* Make sure we have a file on there */
  1436.       pstrcpy(mtar_mask,cur_dir);
  1437.       pstrcat(mtar_mask,"*");
  1438.       /*      do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse,True); */
  1439.           pstrcpy(cur_dir,saved_curdir);
  1440.       free(inbuf);free(outbuf);
  1441.     }
  1442.   else
  1443.     {
  1444.       pstrcpy(rname,cur_dir);
  1445.       pstrcat(rname,finfo->name);
  1446.       do_atar(rname,finfo->name,finfo);
  1447.     }
  1448. }
  1449.  
  1450. /****************************************************************************
  1451. Convert from UNIX to DOS file names
  1452. ***************************************************************************/
  1453. static void unfixtarname(char *tptr, char *fp, int l)
  1454. {
  1455.   /* remove '.' from start of file name, convert from unix /'s to
  1456.    * dos \'s in path. Kill any absolute path names.
  1457.    */
  1458.  
  1459.   if (*fp == '.') fp++;
  1460.   if (*fp == '\\' || *fp == '/') fp++;
  1461.  
  1462.   while (l > 0) {
  1463.     int skip;
  1464.     if(( skip = skip_multibyte_char( *fp )) != 0) {
  1465.       if (skip == 2) {
  1466.         *tptr++ = *fp++;
  1467.         *tptr++ = *fp++;
  1468.         l -= 2;
  1469.       } else if (skip == 1) {
  1470.         *tptr++ = *fp++;
  1471.         l--;
  1472.       }
  1473.     } else if (*fp == '/') {
  1474.       *tptr++ = '\\';
  1475.       fp++;
  1476.       l--;
  1477.     } else {
  1478.       *tptr++ = *fp++;
  1479.       l--;
  1480.     }
  1481.   }
  1482. }
  1483.  
  1484. #if 0 /* Removed to get around gcc 'defined but not used' error. */
  1485.  
  1486. /****************************************************************************
  1487. Move to the next block in the buffer, which may mean read in another set of
  1488. blocks.
  1489. ****************************************************************************/
  1490. static int next_block(char *ltarbuf, char *bufferp, int bufsiz)
  1491. {
  1492.   int bufread, total = 0;
  1493.  
  1494.   if (bufferp >= (ltarbuf + bufsiz)) {
  1495.     
  1496.     for (bufread = read(tarhandle, ltarbuf, bufsiz); total < bufsiz; total += bufread) {
  1497.  
  1498.       if (bufread <= 0) { /* An error, return false */
  1499.     return (total > 0 ? -2 : bufread);
  1500.       }
  1501.  
  1502.     }
  1503.  
  1504.     bufferp = ltarbuf;
  1505.  
  1506.   }
  1507.   else {
  1508.  
  1509.     bufferp += TBLOCK;
  1510.  
  1511.   }
  1512.  
  1513.   return(0);
  1514.  
  1515. }
  1516.  
  1517. static int skip_file(int skip)
  1518. {
  1519.  
  1520.   return(0);
  1521. }
  1522.  
  1523. static int get_file(file_info2 finfo)
  1524. {
  1525.  
  1526.   return(0);
  1527.  
  1528. }
  1529.  
  1530. static int get_dir(file_info2 finfo)
  1531. {
  1532.  
  1533.   return(0);
  1534.  
  1535. }
  1536.  
  1537. static char * get_longfilename(file_info2 finfo)
  1538. {
  1539.  
  1540.   return(NULL);
  1541.  
  1542. }
  1543.  
  1544. static char * bufferp;
  1545.  
  1546. static void do_tarput2(void)
  1547. {
  1548.   file_info2 finfo, *finfo2;
  1549.   struct timeval tp_start;
  1550.   char *inbuf, *outbuf, *longfilename = NULL;
  1551.   int skip = False;
  1552.  
  1553.   GetTimeOfDay(&tp_start);
  1554.  
  1555.   bufferp = tarbuf + tbufsiz;  /* init this to force first read */
  1556.  
  1557.   if (push_dir(&dir_stack, &finfo)) {
  1558.  
  1559.     finfo2 = pop_dir(&dir_stack);
  1560.     inbuf = top_dir_name(&dir_stack); /* FIXME */
  1561.     if (sub_dir(inbuf, finfo2 -> name)){
  1562.  
  1563.       DEBUG(0, (""));
  1564.  
  1565.     }
  1566.   }
  1567.  
  1568.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1569.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1570.  
  1571.   if (!inbuf || !outbuf) {
  1572.  
  1573.     DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n"));
  1574.     return;
  1575.  
  1576.   }
  1577.  
  1578.   if (next_block(tarbuf, bufferp, tbufsiz) <= 0) {
  1579.  
  1580.     DEBUG(0, ("Empty file or short tar file: %s\n", strerror(errno)));
  1581.  
  1582.   }
  1583.  
  1584.   /* Now read through those files ... */
  1585.  
  1586.   while (True) {
  1587.  
  1588.     switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir)) {
  1589.  
  1590.     case -2:    /* Hmm, not good, but not fatal */
  1591.       DEBUG(0, ("Skipping %s...\n", finfo.name));
  1592.       if ((next_block(tarbuf, bufferp, tbufsiz) <= 0) &&
  1593.           !skip_file(finfo.size)) {
  1594.  
  1595.     DEBUG(0, ("Short file, bailing out...\n"));
  1596.     free(inbuf); free(outbuf);
  1597.     continue;
  1598.  
  1599.       }
  1600.  
  1601.       break;
  1602.  
  1603.     case -1:
  1604.       DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
  1605.       free(inbuf); free(outbuf);
  1606.       return;
  1607.  
  1608.     case 0: /* chksum is zero - looks like an EOF */
  1609.       DEBUG(0, ("total of %d tar files restored to share\n", ntarf));
  1610.       free(inbuf); free(outbuf);
  1611.       return;        /* Hmmm, bad here ... */
  1612.  
  1613.     default:
  1614.       break;
  1615.  
  1616.     }
  1617.  
  1618.     /* Now, do we have a long file name? */
  1619.  
  1620.     if (longfilename != NULL) {
  1621.       if (strlen(longfilename) < sizeof(finfo.name)) { /* if we have space */
  1622.  
  1623.     strncpy(finfo.name, longfilename, sizeof(finfo.name) - 1);
  1624.     free(longfilename);
  1625.     longfilename = NULL;
  1626.  
  1627.       }
  1628.       else {
  1629.  
  1630.     DEBUG(0, ("filename: %s too long, skipping\n", strlen(longfilename)));
  1631.     skip = True;
  1632.  
  1633.       }
  1634.     }
  1635.  
  1636.     /* Well, now we have a header, process the file ... */
  1637.  
  1638.     /* Should we skip the file?                         */
  1639.  
  1640.     if (skip) {
  1641.  
  1642.       skip_file(finfo.size);
  1643.       continue;
  1644.  
  1645.     }
  1646.  
  1647.     /* We only get this far if we should process the file */
  1648.  
  1649.     switch (((union hblock *)bufferp) -> dbuf.linkflag) {
  1650.  
  1651.     case '0':  /* Should use symbolic names--FIXME */
  1652.       get_file(finfo);
  1653.       break;
  1654.  
  1655.     case '5':
  1656.       get_dir(finfo);
  1657.       break;
  1658.  
  1659.     case 'L':
  1660.       longfilename = get_longfilename(finfo);
  1661.       break;
  1662.  
  1663.     default:
  1664.       skip_file(finfo.size);  /* Don't handle these yet */
  1665.       break;
  1666.  
  1667.     }
  1668.  
  1669.   }
  1670.  
  1671.  
  1672. }
  1673. #endif /* Removed to get around gcc 'defined but not used' error. */
  1674.  
  1675. static void do_tarput()
  1676. {
  1677.   file_info2 finfo;
  1678.   int nread=0, bufread;
  1679.   char *inbuf,*outbuf, *longname = NULL; 
  1680.   int fsize=0;
  1681.   int fnum;
  1682.   struct timeval tp_start;
  1683.   BOOL tskip=False;       /* We'll take each file as it comes */
  1684.  
  1685.   finfo.name = NULL;      /* No name in here ... */
  1686.  
  1687.   GetTimeOfDay(&tp_start);
  1688.   
  1689.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1690.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1691.   
  1692.   if (!inbuf || !outbuf)
  1693.     {
  1694.       DEBUG(0,("out of memory\n"));
  1695.       return;
  1696.     }
  1697.   
  1698.   /*
  1699.    * Must read in tbufsiz dollops
  1700.    */
  1701.  
  1702.   /* These should be the only reads in clitar.c */
  1703.   while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
  1704.     char *buffer_p, *endofbuffer;
  1705.     int chunk;
  1706.  
  1707.     /* Code to handle a short read.
  1708.      * We always need a TBLOCK full of stuff
  1709.      */
  1710.     if (bufread % TBLOCK) {
  1711.       int lchunk=TBLOCK-(bufread % TBLOCK);
  1712.       int lread;
  1713.  
  1714.       /* It's a shorty - a short read that is */
  1715.       DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk));
  1716.  
  1717.       while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) {
  1718.     bufread+=lread;
  1719.     if (!(lchunk-=lread)) break;
  1720.       }
  1721.  
  1722.       /* If we've reached EOF then that must be a short file */
  1723.       if (lread<=0) break;
  1724.     }
  1725.  
  1726.     buffer_p=tarbuf; 
  1727.     endofbuffer=tarbuf+bufread;
  1728.  
  1729.     if (tskip) {
  1730.       if (fsize<bufread) {
  1731.     tskip=False;
  1732.     buffer_p+=fsize;
  1733.     fsize=0;
  1734.       } else {
  1735.     if (fsize==bufread) tskip=False;
  1736.     fsize-=bufread;
  1737.     continue;
  1738.       }
  1739.     }
  1740.  
  1741.     do {
  1742.       if (!fsize)
  1743.     {
  1744.           int next_header = 1;  /* Want at least one header */
  1745.           while (next_header) 
  1746.             {  
  1747.             if (buffer_p >= endofbuffer) {
  1748.  
  1749.               bufread = read(tarhandle, tarbuf, tbufsiz);
  1750.               buffer_p = tarbuf;
  1751.  
  1752.             }
  1753.             next_header = 0;    /* Don't want the next one ... */
  1754.  
  1755.         if (finfo.name != NULL) { /* Free the space */
  1756.  
  1757.           free(finfo.name);
  1758.           finfo.name = NULL;
  1759.  
  1760.         }
  1761.         switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir))
  1762.           {
  1763.           case -2:             /* something dodgy but not fatal about this */
  1764.             DEBUG(0, ("skipping %s...\n", finfo.name));
  1765.             buffer_p+=TBLOCK;   /* header - like a link */
  1766.             continue;
  1767.           case -1:
  1768.             DEBUG(0, ("abandoning restore, -1 from readtarheader\n"));
  1769.             free(inbuf); free(outbuf);
  1770.             return;
  1771.           case 0: /* chksum is zero - we assume that one all zero
  1772.                  *header block will do for eof */
  1773.             DEBUG(0,
  1774.               ("total of %d tar files restored to share\n", ntarf));
  1775.             free(inbuf); free(outbuf);
  1776.             return;
  1777.           default:
  1778.             break;
  1779.           }
  1780.  
  1781.             /* If we have a longname left from the last time through, 
  1782.                copy it into finfo.name and free it.
  1783.  
  1784.                The size of a pstring is the limiting factor on filenames
  1785.                and directory names now. The total pathname length must be
  1786.                less than sizeof(pstring) - 1, which is currently 1023. */
  1787.  
  1788.             if (longname != NULL) {
  1789.  
  1790.           free(finfo.name);  /* Free the name in the finfo */
  1791.           finfo.name = string_create_s(strlen(longname) + 2);
  1792.               strncpy(finfo.name, longname, strlen(longname) + 1);
  1793.           DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name));
  1794.               free(longname);
  1795.               longname = NULL;
  1796.  
  1797.             }
  1798.  
  1799.             /* Check if a long-link. We do this before the clip checking
  1800.                because clip-checking should clip on real name - RJS */
  1801.  
  1802.             if (((union hblock *)buffer_p) -> dbuf.linkflag == 'L') {
  1803.  
  1804.               /* Skip this header, but pick up length, get the name and 
  1805.                  fix the name and skip the name. Hmmm, what about end of
  1806.                  buffer??? */
  1807.  
  1808.           DEBUG(5, ("Buffer size = %i\n", finfo.size + strlen(cur_dir) +1));
  1809.               longname = malloc(finfo.size + strlen(cur_dir) + 1);
  1810.               if (longname == NULL) {
  1811.  
  1812.                  DEBUG(0, ("could not allocate buffer of size %d for longname\n",
  1813.                     finfo.size + strlen(cur_dir) + 1)
  1814.                       );
  1815.                  free(inbuf); free(outbuf);
  1816.                  return;
  1817.               }
  1818.  
  1819.               buffer_p += TBLOCK;   /* Skip that longlink header */
  1820.  
  1821.               /* This needs restructuring ... */
  1822.  
  1823.           if (buffer_p >= endofbuffer) {
  1824.  
  1825.         bufread = read(tarhandle, tarbuf, tbufsiz);
  1826.  
  1827.         buffer_p = tarbuf;
  1828.  
  1829.               }
  1830.  
  1831.               strncpy(longname, cur_dir, strlen(cur_dir) + 1); 
  1832.               unfixtarname(longname+strlen(cur_dir), buffer_p, finfo.size);
  1833.           DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
  1834.  
  1835.               /* Next rounds up to next TBLOCK and takes care of us being right
  1836.                  on a TBLOCK boundary */
  1837.  
  1838.               buffer_p += (((finfo.size - 1)/TBLOCK)+1)*TBLOCK;
  1839.               next_header = 1;  /* Force read of next header */
  1840.  
  1841.             }
  1842.           }
  1843.       tskip=clipn
  1844.         && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
  1845. #ifdef HAVE_REGEX_H
  1846.         || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
  1847. #else
  1848.             || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
  1849. #endif
  1850.       if (tskip) {
  1851.         buffer_p+=TBLOCK;
  1852.         if (finfo.mode & aDIR)
  1853.           continue;
  1854.         else if ((fsize=finfo.size) % TBLOCK) {
  1855.           fsize+=TBLOCK-(fsize%TBLOCK);
  1856.         }
  1857.         if (fsize<endofbuffer-buffer_p) {
  1858.           buffer_p+=fsize;
  1859.           fsize=0;
  1860.           continue;
  1861.         } else {
  1862.           fsize-=endofbuffer-buffer_p;
  1863.           break;
  1864.         }
  1865.       }
  1866.  
  1867.       DEBUG(5, ("do_tarput: File is: %s\n", finfo.name));
  1868.  
  1869.       if (finfo.mode & aDIR)
  1870.         {
  1871.  
  1872.           DEBUG(5, ("Creating directory: %s\n", finfo.name));
  1873.  
  1874.           if (!ensurepath(finfo.name, inbuf, outbuf))
  1875.         {
  1876.           DEBUG(0, ("abandoning restore, problems ensuring path\n"));
  1877.           free(inbuf); free(outbuf);
  1878.           return;
  1879.           }
  1880.           else
  1881.         {
  1882.           /* Now we update the creation date ... */
  1883.  
  1884.           DEBUG(0, ("Updating creation date on %s\n", finfo.name));
  1885.  
  1886.           if (!do_setrtime(finfo.name, finfo.mtime)) {
  1887.  
  1888.                     DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
  1889.                     return;
  1890.  
  1891.                   }
  1892.  
  1893.           ntarf++;
  1894.           buffer_p+=TBLOCK;
  1895.           continue;
  1896.         }
  1897.         }
  1898.       
  1899.       fsize=finfo.size;
  1900.  
  1901.       if (ensurepath(finfo.name, inbuf, outbuf)
  1902.           && !smbcreat(finfo, &fnum, inbuf, outbuf))
  1903.         {
  1904.           DEBUG(0, ("abandoning restore\n"));
  1905.           free(inbuf);free(outbuf);
  1906.           return;
  1907.         }
  1908.  
  1909.       DEBUG(0 ,("restore tar file %s of size %d bytes\n",
  1910.            finfo.name,finfo.size));
  1911.  
  1912.       /*          if (!finfo.size) {
  1913.         if (!smbshut(finfo, fnum, inbuf, outbuf)){
  1914.               DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name));
  1915.           free(inbuf);free(outbuf);
  1916.               return;
  1917.             }
  1918.         } */
  1919.  
  1920.       nread=0;
  1921.       if ((buffer_p+=TBLOCK) >= endofbuffer) break;      
  1922.     } /* if (!fsize) */
  1923.     
  1924.       /* write out the file in chunk sized chunks - don't
  1925.        * go past end of buffer though */
  1926.       chunk=(fsize-nread < endofbuffer - buffer_p)
  1927.     ? fsize - nread : endofbuffer - buffer_p;
  1928.       
  1929.       while (chunk > 0) {
  1930.     int minichunk=MIN(chunk, max_xmit-200);
  1931.     
  1932.     if (!smbwrite(fnum, /* file descriptor */
  1933.               minichunk, /* n */
  1934.               nread, /* offset low */
  1935.               0, /* offset high - not implemented */
  1936.               fsize-nread, /* left - only hint to server */
  1937.               buffer_p,
  1938.               inbuf,
  1939.               outbuf))
  1940.       {
  1941.         DEBUG(0, ("Error writing remote file\n"));
  1942.         free(inbuf); free(outbuf);
  1943.         return;
  1944.       }
  1945.     DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize));
  1946.     
  1947.     buffer_p+=minichunk; nread+=minichunk;
  1948.     chunk-=minichunk;
  1949.       }
  1950.  
  1951.       if (nread>=fsize)
  1952.     {
  1953.       if (!smbshut(finfo, fnum, inbuf, outbuf))
  1954.         {
  1955.           DEBUG(0, ("Error closing remote file\n"));
  1956.           free(inbuf);free(outbuf);
  1957.           return;
  1958.         }
  1959.       if (fsize % TBLOCK) buffer_p+=TBLOCK - (fsize % TBLOCK);
  1960.       DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
  1961.             (long) buffer_p, (long)(buffer_p - tarbuf)));
  1962.       ntarf++;
  1963.       fsize=0;
  1964.  
  1965.     }
  1966.     } while (buffer_p < endofbuffer);
  1967.   }
  1968.  
  1969.   DEBUG(0, ("premature eof on tar file ?\n"));
  1970.   DEBUG(0,("total of %d tar files restored to share\n", ntarf));
  1971.  
  1972.   free(inbuf); free(outbuf);
  1973. }
  1974.  
  1975. /*
  1976.  * samba interactive commands
  1977.  */
  1978.  
  1979. /****************************************************************************
  1980. Blocksize command
  1981. ***************************************************************************/
  1982. void cmd_block(char *dum_in, char *dum_out)
  1983. {
  1984.   fstring buf;
  1985.   int block;
  1986.  
  1987.   if (!next_token(NULL,buf,NULL))
  1988.     {
  1989.       DEBUG(0, ("blocksize <n>\n"));
  1990.       return;
  1991.     }
  1992.  
  1993.   block=atoi(buf);
  1994.   if (block < 0 || block > 65535)
  1995.     {
  1996.       DEBUG(0, ("blocksize out of range"));
  1997.       return;
  1998.     }
  1999.  
  2000.   blocksize=block;
  2001.   DEBUG(2,("blocksize is now %d\n", blocksize));
  2002. }
  2003.  
  2004. /****************************************************************************
  2005. command to set incremental / reset mode
  2006. ***************************************************************************/
  2007. void cmd_tarmode(char *dum_in, char *dum_out)
  2008. {
  2009.   fstring buf;
  2010.  
  2011.   while (next_token(NULL,buf,NULL)) {
  2012.     if (strequal(buf, "full"))
  2013.       tar_inc=False;
  2014.     else if (strequal(buf, "inc"))
  2015.       tar_inc=True;
  2016.     else if (strequal(buf, "reset"))
  2017.       tar_reset=True;
  2018.     else if (strequal(buf, "noreset"))
  2019.       tar_reset=False;
  2020.     else if (strequal(buf, "system"))
  2021.       tar_system=True;
  2022.     else if (strequal(buf, "nosystem"))
  2023.       tar_system=False;
  2024.     else if (strequal(buf, "hidden"))
  2025.       tar_hidden=True;
  2026.     else if (strequal(buf, "nohidden"))
  2027.       tar_hidden=False;
  2028.     else if (strequal(buf, "verbose") || strequal(buf, "noquiet"))
  2029.       tar_noisy=True;
  2030.     else if (strequal(buf, "quiet") || strequal(buf, "noverbose"))
  2031.       tar_noisy=False;
  2032.     else DEBUG(0, ("tarmode: unrecognised option %s\n", buf));
  2033.   }
  2034.  
  2035.   DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n",
  2036.         tar_inc ? "incremental" : "full",
  2037.         tar_system ? "system" : "nosystem",
  2038.         tar_hidden ? "hidden" : "nohidden",
  2039.         tar_reset ? "reset" : "noreset",
  2040.         tar_noisy ? "verbose" : "quiet"));
  2041.  
  2042. }
  2043.  
  2044. /****************************************************************************
  2045. Feeble attrib command
  2046. ***************************************************************************/
  2047. void cmd_setmode(char *dum_in, char *dum_out)
  2048. {
  2049.   char *q;
  2050.   fstring buf;
  2051.   pstring fname;
  2052.   int attra[2];
  2053.   int direct=1;
  2054.  
  2055.   attra[0] = attra[1] = 0;
  2056.  
  2057.   if (!next_token(NULL,buf,NULL))
  2058.     {
  2059.       DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
  2060.       return;
  2061.     }
  2062.  
  2063.   pstrcpy(fname, cur_dir);
  2064.   pstrcat(fname, buf);
  2065.  
  2066.   while (next_token(NULL,buf,NULL)) {
  2067.     q=buf;
  2068.  
  2069.     while(*q)
  2070.       switch (*q++) {
  2071.       case '+': direct=1;
  2072.     break;
  2073.       case '-': direct=0;
  2074.     break;
  2075.       case 'r': attra[direct]|=aRONLY;
  2076.     break;
  2077.       case 'h': attra[direct]|=aHIDDEN;
  2078.     break;
  2079.       case 's': attra[direct]|=aSYSTEM;
  2080.     break;
  2081.       case 'a': attra[direct]|=aARCH;
  2082.     break;
  2083.       default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
  2084.     return;
  2085.       }
  2086.   }
  2087.  
  2088.   if (attra[ATTRSET]==0 && attra[ATTRRESET]==0)
  2089.     {
  2090.       DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
  2091.       return;
  2092.     }
  2093.  
  2094.   DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET]));
  2095.   (void) do_setrattr(fname, attra[ATTRSET], ATTRSET);
  2096.   (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET);
  2097. }
  2098.  
  2099. /****************************************************************************
  2100. Principal command for creating / extracting
  2101. ***************************************************************************/
  2102. void cmd_tar(char *inbuf, char *outbuf)
  2103. {
  2104.   fstring buf;
  2105.   char **argl;
  2106.   int argcl;
  2107.  
  2108.   if (!next_token(NULL,buf,NULL))
  2109.     {
  2110.       DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
  2111.       return;
  2112.     }
  2113.  
  2114.   argl=toktocliplist(&argcl, NULL);
  2115.   if (!tar_parseargs(argcl, argl, buf, 0))
  2116.     return;
  2117.  
  2118.   process_tar(inbuf, outbuf);
  2119.  
  2120.   free(argl);
  2121. }
  2122.  
  2123. /****************************************************************************
  2124. Command line (option) version
  2125. ***************************************************************************/
  2126. int process_tar(char *inbuf, char *outbuf)
  2127. {
  2128.   initarbuf();
  2129.   switch(tar_type) {
  2130.   case 'x':
  2131.  
  2132. #if 0
  2133.     do_tarput2();
  2134. #else
  2135.     do_tarput();
  2136. #endif
  2137.     free(tarbuf);
  2138.     close(tarhandle);
  2139.     break;
  2140.   case 'r':
  2141.   case 'c':
  2142.     if (clipn && tar_excl) {
  2143.       int i;
  2144.       pstring tarmac;
  2145.  
  2146.       for (i=0; i<clipn; i++) {
  2147.     DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
  2148.  
  2149.     if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
  2150.       *(cliplist[i]+strlen(cliplist[i])-1)='\0';
  2151.     }
  2152.     
  2153.     if (strrchr(cliplist[i], '\\')) {
  2154.       pstring saved_dir;
  2155.       
  2156.       pstrcpy(saved_dir, cur_dir);
  2157.       
  2158.       if (*cliplist[i]=='\\') {
  2159.         pstrcpy(tarmac, cliplist[i]);
  2160.       } else {
  2161.         pstrcpy(tarmac, cur_dir);
  2162.         pstrcat(tarmac, cliplist[i]);
  2163.       }
  2164.       pstrcpy(cur_dir, tarmac);
  2165.       *(strrchr(cur_dir, '\\')+1)='\0';
  2166.  
  2167.       do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
  2168.       pstrcpy(cur_dir,saved_dir);
  2169.     } else {
  2170.       pstrcpy(tarmac, cur_dir);
  2171.       pstrcat(tarmac, cliplist[i]);
  2172.       do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse, True);
  2173.     }
  2174.       }
  2175.     } else {
  2176.       pstring mask;
  2177.       pstrcpy(mask,cur_dir);
  2178.       pstrcat(mask,"\\*");
  2179.       do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse, True);
  2180.     }
  2181.     
  2182.     if (ntarf) dotareof(tarhandle);
  2183.     close(tarhandle);
  2184.     free(tarbuf);
  2185.     
  2186.     DEBUG(0, ("tar: dumped %d tar files\n", ntarf));
  2187.     DEBUG(0, ("Total bytes written: %d\n", ttarf));
  2188.     break;
  2189.   }
  2190.  
  2191.   return(0);
  2192. }
  2193.  
  2194. /****************************************************************************
  2195. Find a token (filename) in a clip list
  2196. ***************************************************************************/
  2197. int clipfind(char **aret, int ret, char *tok)
  2198. {
  2199.   if (aret==NULL) return 0;
  2200.  
  2201.   /* ignore leading slashes or dots in token */
  2202.   while(strchr("/\\.", *tok)) tok++;
  2203.  
  2204.   while(ret--) {
  2205.     char *pkey=*aret++;
  2206.  
  2207.     /* ignore leading slashes or dots in list */
  2208.     while(strchr("/\\.", *pkey)) pkey++;
  2209.  
  2210.     if (!strslashcmp(pkey, tok)) return 1;
  2211.   }
  2212.  
  2213.   return 0;
  2214. }
  2215.  
  2216. /****************************************************************************
  2217. Parse tar arguments. Sets tar_type, tar_excl, etc.
  2218. ***************************************************************************/
  2219. int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
  2220. {
  2221.   char tar_clipfl='\0';
  2222.  
  2223.   /* Reset back to defaults - could be from interactive version 
  2224.    * reset mode and archive mode left as they are though
  2225.    */
  2226.   tar_type='\0';
  2227.   tar_excl=True;
  2228.  
  2229.   while (*Optarg) 
  2230.     switch(*Optarg++) {
  2231.     case 'c':
  2232.       tar_type='c';
  2233.       break;
  2234.     case 'x':
  2235.       if (tar_type=='c') {
  2236.     printf("Tar must be followed by only one of c or x.\n");
  2237.     return 0;
  2238.       }
  2239.       tar_type='x';
  2240.       break;
  2241.     case 'b':
  2242.       if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) {
  2243.     DEBUG(0,("Option b must be followed by valid blocksize\n"));
  2244.     return 0;
  2245.       } else {
  2246.     Optind++;
  2247.       }
  2248.       break;
  2249.     case 'g':
  2250.       tar_inc=True;
  2251.       break;
  2252.     case 'N':
  2253.       if (Optind>=argc) {
  2254.     DEBUG(0,("Option N must be followed by valid file name\n"));
  2255.     return 0;
  2256.       } else {
  2257.     struct stat stbuf;
  2258.     extern time_t newer_than;
  2259.     
  2260.     if (sys_stat(argv[Optind], &stbuf) == 0) {
  2261.       newer_than = stbuf.st_mtime;
  2262.       DEBUG(1,("Getting files newer than %s",
  2263.            asctime(LocalTime(&newer_than))));
  2264.       Optind++;
  2265.     } else {
  2266.       DEBUG(0,("Error setting newer-than time\n"));
  2267.       return 0;
  2268.     }
  2269.       }
  2270.       break;
  2271.     case 'a':
  2272.       tar_reset=True;
  2273.       break;
  2274.     case 'I':
  2275.       if (tar_clipfl) {
  2276.     DEBUG(0,("Only one of I,X must be specified\n"));
  2277.     return 0;
  2278.       }
  2279.       tar_clipfl='I';
  2280.       break;
  2281.     case 'X':
  2282.       if (tar_clipfl) {
  2283.     DEBUG(0,("Only one of I,X must be specified\n"));
  2284.     return 0;
  2285.       }
  2286.       tar_clipfl='X';
  2287.       break;
  2288.     case 'r':
  2289.       DEBUG(0, ("tar_re_search set\n"));
  2290.       tar_re_search = True;
  2291.       break;
  2292.     default:
  2293.       DEBUG(0,("Unknown tar option\n"));
  2294.       return 0;
  2295.     }
  2296.  
  2297.   if (!tar_type) {
  2298.     printf("Option T must be followed by one of c or x.\n");
  2299.     return 0;
  2300.   }
  2301.  
  2302.   tar_excl=tar_clipfl!='X';
  2303.  
  2304.   if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
  2305.     char *tmpstr;
  2306.     char **tmplist;
  2307.     int clipcount;
  2308.  
  2309.     cliplist=argv+Optind+1;
  2310.     clipn=argc-Optind-1;
  2311.     clipcount = clipn;
  2312.  
  2313.     if ((tmplist=malloc(clipn*sizeof(char *))) == NULL) {
  2314.       DEBUG(0, ("Could not allocate space to process cliplist, count = %i\n", 
  2315.                clipn)
  2316.            );
  2317.       return 0;
  2318.     }
  2319.  
  2320.     for (clipcount = 0; clipcount < clipn; clipcount++) {
  2321.  
  2322.       DEBUG(5, ("Processing an item, %s\n", cliplist[clipcount]));
  2323.  
  2324.       if ((tmpstr = (char *)malloc(strlen(cliplist[clipcount])+1)) == NULL) {
  2325.         DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n",
  2326.                  clipcount)
  2327.              );
  2328.         return 0;
  2329.       }
  2330.       unfixtarname(tmpstr, cliplist[clipcount], strlen(cliplist[clipcount]) + 1);
  2331.       tmplist[clipcount] = tmpstr;
  2332.       DEBUG(5, ("Processed an item, %s\n", tmpstr));
  2333.  
  2334.       DEBUG(5, ("Cliplist is: %s\n", cliplist[0]));
  2335.     }
  2336.     cliplist = tmplist;
  2337.   }
  2338.  
  2339.   if (Optind+1<argc && tar_re_search) {  /* Doing regular expression seaches */
  2340. #ifdef HAVE_REGEX_H
  2341.     int errcode;
  2342.  
  2343.     if ((preg = (regex_t *)malloc(65536)) == NULL) {
  2344.  
  2345.       DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
  2346.       return;
  2347.  
  2348.     }
  2349.  
  2350.     if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
  2351.       char errstr[1024];
  2352.       size_t errlen;
  2353.  
  2354.       errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
  2355.       
  2356.       DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
  2357.       return;
  2358.  
  2359.     }
  2360. #endif
  2361.  
  2362.     clipn=argc-Optind-1;
  2363.     cliplist=argv+Optind+1;
  2364.  
  2365.   }
  2366.  
  2367.   if (Optind>=argc || !strcmp(argv[Optind], "-")) {
  2368.     /* Sets tar handle to either 0 or 1, as appropriate */
  2369.     tarhandle=(tar_type=='c');
  2370.   } else {
  2371.     if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
  2372.     || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
  2373.       {
  2374.     DEBUG(0,("Error opening local file %s - %s\n",
  2375.          argv[Optind], strerror(errno)));
  2376.     return(0);
  2377.       }
  2378.   }
  2379.  
  2380.   return 1;
  2381. }
  2382.